package coroutine

import (
	"codeup.aliyun.com/5f9118049cffa29cfdd3be1c/util"
	"fmt"
	"runtime/debug"
	"sync"
)

var activeTaskMu sync.Mutex
var activeTask = make(map[*task]struct{})
var globalLogger util.Logger

type task struct {
	name string
	fn   func()
}

// addTask 添加任务
func addTask(t *task) {
	activeTaskMu.Lock()
	defer activeTaskMu.Unlock()
	activeTask[t] = struct{}{}
}

// removeTask 删除任务
func removeTask(t *task) {
	activeTaskMu.Lock()
	defer activeTaskMu.Unlock()
	delete(activeTask, t)
}

// getTaskSize 获取任务数量
// nolint
func getTaskSize() int {
	activeTaskMu.Lock()
	defer activeTaskMu.Unlock()
	return len(activeTask)
}

// getTaskSize 获取任务数量
func getTasks() []*task {
	activeTaskMu.Lock()
	defer activeTaskMu.Unlock()

	tasks := make([]*task, 0, len(activeTask))
	for t := range activeTask {
		tasks = append(tasks, t)
	}
	return tasks
}

// Run 运行指定函数
// name 协程名称
// fn 协程执行的函数
func Run(name string, fn func()) {
	runAfter(name, fn, func() {})
}

// Run 运行指定函数
// name 协程名称
// fn 协程执行的函数
func runAfter(name string, fn func(), afterFn func()) {
	t := &task{name: name, fn: fn}
	addTask(t)

	go func() {
		// 删除任务
		defer removeTask(t)

		// 记录panic错误
		defer func() {
			if r := recover(); r != nil {
				if globalLogger != nil {
					globalLogger.Errorf("coroutine %s panic：%+v", t.name, r)
				} else {
					fmt.Printf("coroutine %s panic：%+v", t.name, r)
				}
				debug.PrintStack()
			}
		}()

		// 完毕后要执行的函数
		defer afterFn()

		// 运行指定函数
		t.fn()
	}()
}
